package com.example.lottery_system.service.activitystatus.impl;

import com.example.lottery_system.common.utils.JacksonUtil;
import com.example.lottery_system.service.ActivityService;
import com.example.lottery_system.service.activitystatus.ActivityStatusManager;
import com.example.lottery_system.service.activitystatus.operator.AbstractActivityOperator;
import com.example.lottery_system.service.dto.ActivityDetailDTO;
import com.example.lottery_system.service.dto.DrawPrizeStatusDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Service
public class ActivityStatusManagerImpl implements ActivityStatusManager {

    Logger logger = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);

    @Autowired
    ActivityService activityService;
    @Autowired
    Map<String, AbstractActivityOperator> operatorMap = new HashMap<>();

    @Override
    /**
     * 保证事务的一致性， 设置了遇到异常就进行事务的回滚操作
     */
    @Transactional(rollbackFor = Exception.class)
    public void handlerEvent(DrawPrizeStatusDto drawPrizeStatusDto) {
        /**
         * 1. 判空一下
         */
        if (CollectionUtils.isEmpty(operatorMap)) {
            logger.warn("DrawPrizeStatusDto::operatorMap为空!");
            return;
        }

        Map<String, AbstractActivityOperator> curMap = new HashMap<>(operatorMap);

        /**
         * 2. 修改状态
         */
        boolean update1 = processConvertStatus(drawPrizeStatusDto, curMap, 1);
        boolean update2 = processConvertStatus(drawPrizeStatusDto, curMap, 2);

//        只要有修改就更新缓存活动信息
        if (update1 || update2) {
//            如果一旦有修改，就需要修改缓存
            /**
             * 修改状态时，需要实时的更新数据库和缓存中的状态
             */
            ActivityDetailDTO activityDetailDTO = activityService.getActivityDetailDTO(drawPrizeStatusDto.getActivityId());
            activityService.cacheActivityToRedis(activityDetailDTO);
        }

    }

    @Override
    public void rollBackEvent(DrawPrizeStatusDto drawPrizeStatusDto) {
        if (null == drawPrizeStatusDto) {
            logger.warn("rollBackEvent::DrawPrizeStatusDto为空！");
            return;
        }

//        全部重新回滚成running
        for (AbstractActivityOperator abstractActivityOperator : operatorMap.values()) {
            abstractActivityOperator.convert(drawPrizeStatusDto);
        }

//        重新更新缓存的信息
        /**
         *  当回滚结束后也需要同步缓存和数据库的数据的一致性
         *
         */
        ActivityDetailDTO activityDetailDTO = activityService.getActivityDetailDTO(drawPrizeStatusDto.getActivityId());
        activityService.cacheActivityToRedis(activityDetailDTO);

    }

    private boolean processConvertStatus(DrawPrizeStatusDto drawPrizeStatusDto, Map<String, AbstractActivityOperator> curMap, int sequence) {

        boolean update = false;
//        获取 迭代器
        Iterator<Map.Entry<String, AbstractActivityOperator>> iterator = curMap.entrySet().iterator();
        while (iterator.hasNext()) {
            AbstractActivityOperator abstractActivityOperator = iterator.next().getValue();
//            检查当前次序是否正确
            if (!abstractActivityOperator.sequence().equals(sequence)) {
                continue;
            }

//            检查是否需要转化
            if (!abstractActivityOperator.needConvert(drawPrizeStatusDto)) {
                continue;
            }

//            进行转化
            if (!abstractActivityOperator.convert(drawPrizeStatusDto)) {
                logger.warn("{}abstractActivityOperator转化失败", JacksonUtil.writeValueAsString(drawPrizeStatusDto));
                return false;
            }

            // 移除当前迭代器元素
            iterator.remove();
            update = true;
        }

        return update;
    }
}
